import { uploadRelativeFileNew as uploadRelativeFileAPI } from '@/api/pc/elderly';
import { ElMessage } from 'element-plus';

/**
 * 文件上传工具类
 * 提供统一的文件上传接口，支持亲属相关的各种文件类型
 */
class FileUploader {
  /**
   * 生成临时亲属ID
   * 参照后台逻辑：temp_' + new Date().getTime() + '_' + Math.random().toString(36).substr(2, 9)
   * @returns {string} 临时亲属ID
   */
  static generateTempRelativeId() {
    return 'temp_' + new Date().getTime() + '_' + Math.random().toString(36).substr(2, 9);
  }
  /**
   * 上传亲属相关文件
   * @param {File} file - 要上传的文件
   * @param {string} userId - 用户ID
   * @param {string} fileType - 文件类型（可选，自动判断）
   * @param {string} relativeId - 亲属ID（可选）
   * @param {string} context - 上传上下文，用于自动判断文件类型
   * @param {number} mode - 上传模式：1=个人信息(不传relativeId)，2=创建角色(传临时ID)，3=编辑角色(传实际ID)
   * @returns {Promise<string>} 返回文件URL
   */
  static async uploadRelativeFile(file, userId, relativeId = undefined, context = '', mode = 2) {
    try {
      // 根据模式决定如何处理relativeId
      let finalRelativeId = relativeId;
      
      if (mode === 1) {
        // 模式1：个人信息填写 - 不传入relativeId参数或传null
        finalRelativeId = null;
        console.log('个人信息填写模式，relativeId设为null');
      } else if (mode === 2) {
        // 模式2：创建角色 - 使用传入的临时ID，不再重新生成
        if (!relativeId) {
          // 如果没有传入临时ID，才生成一个新的
          finalRelativeId = this.generateTempRelativeId();
          console.log('创建角色模式，未传入临时ID，生成新的临时亲属ID:', finalRelativeId);
        } else {
          // 使用传入的临时ID，确保与创建角色时使用同一个ID
          finalRelativeId = relativeId;
          console.log('创建角色模式，使用传入的临时亲属ID:', finalRelativeId);
        }
      } else if (mode === 3) {
        // 模式3：编辑角色 - 使用传入的实际ID
        if (!relativeId) {
          throw new Error('编辑角色模式必须传入relativeId');
        }
        finalRelativeId = relativeId;
        console.log('编辑角色模式，使用现有ID:', finalRelativeId);
      } else {
        throw new Error('无效的上传模式，必须是1、2或3');
      }
      
      // 自动判断文件类型
      let fileType = this.getFileType(file, context, finalRelativeId);
      
      // 文件压缩优化
      let optimizedFile = file;
      if (/^image\//.test(file.type)) {
        console.log('压缩图片文件...');
        console.log('原始文件大小:', (file.size / 1024).toFixed(1) + 'KB');
        
        // 强制压缩，不管原图尺寸
        optimizedFile = await this.compressImage(file, {
          maxWidth: 512, // 降低到512px
          maxHeight: 512, // 降低到512px
          quality: 0.5, // 降低质量到0.5
          maxSize: 200 * 1024, // 目标200KB
          forceCompress: true // 强制压缩
        });
      } else if (/^audio\//.test(file.type)) {
        console.log('压缩音频文件...');
        optimizedFile = await this.compressAudio(file, {
          maxSize: 2 * 1024 * 1024 // 2MB
        });
      }
      
      console.log(`文件优化: ${(file.size / 1024).toFixed(1)}KB -> ${(optimizedFile.size / 1024).toFixed(1)}KB`);
      
      // 调用新的文件上传接口
      console.log('调用文件上传API，参数:', {
        file: optimizedFile.name,
        userId: userId,
        fileType: fileType,
        relativeId: finalRelativeId,
        relativeIdType: typeof finalRelativeId
      });
      
      const response = await uploadRelativeFileAPI(
        optimizedFile, 
        userId, 
        fileType, 
        finalRelativeId
      );
      
      if (response.code === 200 && response.data && response.data.length > 0) {
        const fileData = response.data[0];
        const fileUrl = fileData.fileBase64 || fileData.url || '';
        
        if (!fileUrl) {
          throw new Error('未返回文件URL');
        }
        
        ElMessage.success('上传成功');
        
        // 处理嵌套的 data 结构
        let finalFileData = fileData;
        if (fileData.data && Array.isArray(fileData.data) && fileData.data.length > 0) {
          // 如果存在嵌套的 data 数组，使用第一个元素
          finalFileData = fileData.data[0];
          console.log('检测到嵌套的 data 结构，使用内部数据:', finalFileData);
        }
        
        // 返回完整的文件数据对象，包含所有接口返回的字段
        return {
          fileUrl: fileUrl,
          fileData: finalFileData
        };
      } else {
        throw new Error(response.msg || '上传失败');
      }
    } catch (error) {
      ElMessage.error(error.message || '上传失败');
      console.error('File upload error:', error);
      throw error;
    }
  }

  /**
   * 根据文件类型和上下文自动判断fileType参数
   * 业务逻辑：
   * 1. 角色编辑/创建画面：传入relativeId，照片为角色本人照片(IMAGE_SELF)，音频为角色本人录音(AUDIO_SELF)
   * 2. 个人信息画面：不传入relativeId，照片为用户本人照片(IMAGE_SELF)，音频为用户本人录音(AUDIO_SELF)，家人音频为家人语音(AUDIO_RELATIVE)
   * @param {File} file - 文件对象
   * @param {string} context - 上传上下文
   * @param {string} relativeId - 亲属ID
   * @returns {string} 文件类型标识
   */
  static getFileType(file, context = '', relativeId = '') {
    // 根据文件MIME类型判断
    if (/^image\//.test(file.type)) {
      // 图片文件：无论是否传入relativeId，都是本人照片
      return 'IMAGE_SELF';
    } else if (/^video\//.test(file.type)) {
      // 视频文件：家人视频
      return 'VIDEO_MATERIAL';
    } else if (/^audio\//.test(file.type)) {
      // 音频文件
      if (context === 'relative') {
        // 明确指定为家人语音
        return 'AUDIO_RELATIVE';
      } else {
        // 其他情况都是本人录音
        return 'AUDIO_SELF';
      }
    } else {
      // 其他文件类型
      return 'OTHER_FILE';
    }
  }

  /**
   * 上传头像/图片文件
   * @param {File} file - 图片文件
   * @param {string} userId - 用户ID
   * @param {string} relativeId - 亲属ID（可选）
   * @param {number} mode - 上传模式：1=个人信息，2=创建角色，3=编辑角色
   * @returns {Promise<string>} 返回文件URL
   */
  static async uploadAvatar(file, userId, relativeId = undefined, mode = 2) {
    return this.uploadRelativeFile(file, userId, relativeId, 'avatar', mode);
  }

  /**
   * 上传视频文件
   * @param {File} file - 视频文件
   * @param {string} userId - 用户ID
   * @param {string} relativeId - 亲属ID（可选）
   * @param {number} mode - 上传模式：1=个人信息，2=创建角色，3=编辑角色
   * @returns {Promise<string>} 返回文件URL
   */
  static async uploadVideo(file, userId, relativeId = undefined, mode = 2) {
    return this.uploadRelativeFile(file, userId, relativeId, 'video', mode);
  }

  /**
   * 上传音频文件
   * @param {File} file - 音频文件
   * @param {string} userId - 用户ID
   * @param {string} relativeId - 亲属ID（可选）
   * @param {number} mode - 上传模式：1=个人信息，2=创建角色，3=编辑角色
   * @returns {Promise<string>} 返回文件URL
   */
  static async uploadAudio(file, userId, relativeId = undefined, mode = 2) {
    return this.uploadRelativeFile(file, userId, relativeId, 'voice', mode);
  }

  /**
   * 批量上传文件
   * @param {File[]} files - 文件数组
   * @param {string} userId - 用户ID
   * @param {string} relativeId - 亲属ID（可选）
   * @param {string} context - 上传上下文
   * @param {number} mode - 上传模式：1=个人信息，2=创建角色，3=编辑角色
   * @returns {Promise<string[]>} 返回文件URL数组
   */
  static async uploadMultipleFiles(files, userId, relativeId = undefined, context = '', mode = 2) {
    const uploadPromises = files.map(file => 
      this.uploadRelativeFile(file, userId, relativeId, context, mode)
    );
    
    try {
      const results = await Promise.all(uploadPromises);
      return results;
    } catch (error) {
      console.error('Batch upload failed:', error);
      throw error;
    }
  }

  /**
   * 压缩图片文件
   * @param {File} file - 图片文件
   * @param {Object} options - 压缩选项
   * @returns {Promise<File>} 压缩后的文件
   */
  static async compressImage(file, options = {}) {
    const {
      maxWidth = 512, // 降低到512px
      maxHeight = 512, // 降低到512px
      quality = 0.6, // 降低质量到0.6
      maxSize = 200 * 1024, // 降低到200KB
      forceCompress = false // 是否强制压缩
    } = options;

    return new Promise((resolve) => {
      // 如果文件已经很小且不强制压缩，直接返回
      if (file.size <= maxSize && !forceCompress) {
        console.log('文件已足够小，跳过压缩');
        resolve(file);
        return;
      }
      
      // 强制压缩时，即使文件小也要压缩
      if (forceCompress) {
        console.log('强制压缩模式，开始压缩...');
      }

      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      const img = new Image();
      
      img.onload = () => {
        // 计算压缩后的尺寸
        let { width, height } = img;
        console.log('原始图片尺寸:', width, 'x', height);
        
        // 强制压缩：即使原图尺寸小，也要压缩到目标尺寸
        if (forceCompress || width > maxWidth || height > maxHeight) {
          const ratio = Math.min(maxWidth / width, maxHeight / height);
          width = Math.floor(width * ratio);
          height = Math.floor(height * ratio);
          console.log('压缩后尺寸:', width, 'x', height);
        }
        
        canvas.width = width;
        canvas.height = height;
        
        // 绘制压缩后的图片
        ctx.drawImage(img, 0, 0, width, height);
        
        // 转换为 Blob，使用更低的质量
        canvas.toBlob((blob) => {
          const compressedFile = new File([blob], file.name, {
            type: file.type,
            lastModified: Date.now()
          });
          
          console.log(`图片压缩: ${(file.size / 1024).toFixed(1)}KB -> ${(compressedFile.size / 1024).toFixed(1)}KB`);
          
          // 如果还是太大，进一步压缩
          if (compressedFile.size > maxSize && quality > 0.3) {
            console.log('图片仍然过大，进一步压缩...');
            this.compressImage(compressedFile, {
              ...options,
              quality: quality * 0.8,
              maxWidth: Math.floor(maxWidth * 0.9),
              maxHeight: Math.floor(maxHeight * 0.9)
            }).then(resolve);
          } else {
            console.log('压缩完成，最终大小:', (compressedFile.size / 1024).toFixed(1) + 'KB');
            resolve(compressedFile);
          }
        }, file.type, quality);
      };
      
      img.src = URL.createObjectURL(file);
    });
  }

  /**
   * 压缩音频文件
   * @param {File} file - 音频文件
   * @param {Object} options - 压缩选项
   * @returns {Promise<File>} 压缩后的文件
   */
  static async compressAudio(file, options = {}) {
    const {
      maxSize = 2 * 1024 * 1024, // 2MB
      targetBitrate = 128 // 128kbps
    } = options;

    // 如果文件已经很小，直接返回
    if (file.size <= maxSize) {
      return file;
    }

    // 音频压缩需要 Web Audio API 支持
    if (!window.AudioContext && !window.webkitAudioContext) {
      console.warn('浏览器不支持音频压缩，使用原文件');
      return file;
    }

    try {
      // 这里可以实现音频压缩逻辑
      // 由于音频压缩比较复杂，暂时返回原文件
      console.warn('音频压缩功能待实现，使用原文件');
      return file;
    } catch (error) {
      console.error('音频压缩失败:', error);
      return file;
    }
  }

  /**
   * 验证文件类型和大小
   * @param {File} file - 文件对象
   * @param {Object} options - 验证选项
   * @returns {boolean} 验证是否通过
   */
  static validateFile(file, options = {}) {
    const {
      allowedTypes = ['image/*', 'video/*', 'audio/*'],
      maxSize = 50 * 1024 * 1024, // 默认50MB
      minSize = 0
    } = options;

    // 检查文件类型
    const isTypeAllowed = allowedTypes.some(type => {
      if (type.endsWith('/*')) {
        const baseType = type.replace('/*', '');
        return file.type.startsWith(baseType);
      }
      return file.type === type;
    });

    if (!isTypeAllowed) {
      ElMessage.error(`不支持的文件类型: ${file.type}`);
      return false;
    }

    // 检查文件大小
    if (file.size > maxSize) {
      const maxSizeMB = Math.round(maxSize / 1024 / 1024);
      ElMessage.error(`文件大小不能超过 ${maxSizeMB}MB`);
      return false;
    }

    if (file.size < minSize) {
      const minSizeKB = Math.round(minSize / 1024);
      ElMessage.error(`文件大小不能小于 ${minSizeKB}KB`);
      return false;
    }

    return true;
  }
}

export default FileUploader;
